/************************************************************************
  Scheme interpreter
  
  Copyright (C) 2010 Marioly Garza 

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License as
  published by the Free Software Foundation, either version 3 of the
  License, or (at your option) any later version.
  
  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this program. If not, see
  <http://www.gnu.org/licenses/>.

************************************************************************/

#include "util.h"

bool util::is_atom(object *o)
{
    return !is<pair>(o);
}

bool util::is_string(object *o)
{
    if (util::is<sstring>(o))
    {
        std::string s = (std::string)*((sstring*)o);
        if (s.length() > 1) {
            if (s[0] == '"' && s[s.length()-1] == '"')
                return true;
        }
    }
    return false;
}

bool util::is_number(object *o)
{
    std::string s = ((sstring*)o)->to_string();
    const char *p = s.c_str();
    char c;
    while ((c=*p++)) {
        if (!isdigit(c) && c != '.') return false;
    }
    return true;
}

int util::count(std::string str, const char c)
{
    int pos = 0, n = 0;
    while ((pos = str.find(c, pos)) != std::string::npos) {
        n++;
        pos++;
    }
    return n;
}

const char* util::get_type(object* o)
{
    if (is<pair>(o)) {
        return "pair";
    }
    else if (is<sstring>(o)) {
        return "atom";
    }
    else if (is<sboolean>(o)) {
        return "boolean";
    }
    else
    {
        return "undefined";
    }       
}

char* util::format(std::string format, ...)
{
    char *buffer = new char[250];
    va_list args;
    va_start (args, format);
    vsprintf (buffer, format.c_str(), args);
    va_end (args);

    return buffer;
}

std::string util::stringtify(object* o)
{
    if (o == NULL) return "";
    else if (util::is_atom(o))
    {
        return o->to_string();
    }
    else if (util::is<pair>(o))
    {
        pair* p = (pair*)o;
        std::string res = stringtify(p->car);
        std::string scdr = string_content(stringtify(p->cdr), '(', ')');
        if (!scdr.empty())
            res += ", " + scdr;

        return "(" + res + ")";
    }
    else
    {
        return "undefined?";
    }
}

std::string util::string_content(std::string str, char lv, char rv)
{
    if (!str.empty())
    {
        if (str[0] == lv)
            str = str.substr(1);
        if (str[str.length()-1] == rv)
            str = str.substr(0, str.length()-1);
    }

    return str;
}
